package com.hb.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.FileSystemResource;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.multipart.support.StandardServletMultipartResolver;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.spring4.SpringTemplateEngine;
import org.thymeleaf.spring4.view.ThymeleafViewResolver;
import org.thymeleaf.templateresolver.AbstractTemplateResolver;
import org.thymeleaf.templateresolver.ServletContextTemplateResolver;
import org.thymeleaf.templateresolver.TemplateResolver;

import java.io.IOException;
import java.nio.charset.StandardCharsets;

@Configuration
@EnableWebMvc   // 启用 SpringMVC
@ComponentScan(basePackageClasses = com.hb.web.ComponentScanFlagClass.class)    // 启用组件扫描
public class WebConfig extends WebMvcConfigurerAdapter {
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

    @Bean
    public TemplateResolver templateResolver() {
        TemplateResolver templateResolver = new ServletContextTemplateResolver();
        templateResolver.setPrefix("/WEB-INF/views/");
        templateResolver.setSuffix(".html");
        templateResolver.setTemplateMode("HTML5");
        templateResolver.setCharacterEncoding(StandardCharsets.UTF_8.name());
        return templateResolver;
    }

    @Bean
    public SpringTemplateEngine templateEngine(TemplateResolver templateResolver) {
        SpringTemplateEngine templateEngine = new SpringTemplateEngine();
        templateEngine.setTemplateResolver(templateResolver);
        return templateEngine;
    }

    @Bean
    public ViewResolver viewResolver(SpringTemplateEngine templateEngine) {
        ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
        viewResolver.setTemplateEngine(templateEngine);
        viewResolver.setCharacterEncoding(StandardCharsets.UTF_8.name());
        return viewResolver;
    }

    /**
     * 配置基于 Servlet 3.0 的 multipart 解析器
     * 在 Servlet 3.0 中使用文件上传：DispatcherServlet 配置 Multipart + 使用 StandardServletMultipartResolver
     * @return
     * @throws IOException
     */
    @Bean
    public MultipartResolver multipartResolver() throws IOException {
        // 兼容 Servlet 3.0 的 StandardServletMultipartResolver 没有构造器参数，也没有要设置的属性。
        // 如果我们想要限制用户上传文件的大小，该怎么实现？如果我们想要指定文件在上传时，临时写入目录在什么位置的话，该如何实现？因为没有属性和构造器参数，
        // StandardServletMultipartResolver 的功能看起来似乎有些受限。
        // 我们是有办法配置 StandardServletMultipartResolver 的限制条件的。只不过不是在 Spring 中配置 StandardServletMultipartResolver，
        // 而是要在 Servlet 中指定 multipart 的配置。至少，我们必须要指定在文件上传的过程中，所写入的临时文件路径。如果不设定这个最基本配置的话，
        // StandardServletMultipartResolver 就无法正常工作。具体来讲，我们必须要在 web.xml 或 Servlet 初始化类中，将 multipart 的具体细节作为
        // DispatcherServlet 配置的一部分。
        return new StandardServletMultipartResolver();
    }

    /**
     * 配置 Jakarta Commons FileUpload multipart 解析器
     * 注意如果不引入 commons-fileupload 包的话启动应用时就会报错：nested exception is java.lang.NoClassDefFoundError: org/apache/commons/fileupload/FileItemFactory
     * @return
     */
//    @Bean
//    public MultipartResolver multipartResolverEx() throws IOException {
//        // 1、通常来讲，StandardServletMultipartResolver 会是最佳的选择，但是如果我们需要将应用部署到非 Servlet 3.0 的容器中，那么就得需要替代的方案。
//        // 2、Spring 内置了 CommonsMultipartResolver，可以作为 StandardServletMultipartResolver 的替代方案。
//        // 3、与 StandardServletMultipartResolver 有所不同，CommonsMultipartResolver 不会强制要求设置临时文件路径。默认情况下，这个路径就是 Servlet 容器的临时目录。
//        // 不过，通过设置 uploadTempDir 属性，我们可以将其指定为一个不同的位置。
//        CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
//        multipartResolver.setUploadTempDir(new FileSystemResource("/tmp/spittr/uploads"));
//        // 整个 multipart 请求不超过 4MB
//        multipartResolver.setMaxUploadSize(4194304);
//        // 不能上传超过 2MB 的文件
//        multipartResolver.setMaxUploadSizePerFile(2097152);
//        // 不管文件的大小如何，所有的文件都会写到磁盘中
//        multipartResolver.setMaxInMemorySize(0);
//        return multipartResolver;
//    }
}
